import datetime
import math
import os
from collections import defaultdict
from typing import Any

from task_service import AbsTaskService
from x_tw.core.data_checker import DataChecker
from x_tw.core.data_processor import DataProcessor
from x_tw.db.in_service import TaskDataService
from x_tw.db.out_service import VehicleOrderService, WaveOrderSku
from x_tw.load_fun_new_t_goods_concat_81 import main_fun
from x_tw.util.tools import parse_second


class XTWTaskService(AbsTaskService):
    """
    时间窗
    """
    name: str = 'TW'

    # 打折系数
    dis_value: Any
    # 件箱库流量
    box_flow_value: Any
    # ems同时交付工厂数
    ems_delivery_count: Any
    # zz同时交付工厂数
    zz_delivery_count: Any
    # 出货口配置信息
    port_config_list: Any
    # 出货口对应件箱总数
    port_lpn_num: Any
    # 全局时间参数
    global_time: Any
    # 计算时间
    execution_time: Any
    # 是否分车
    is_split_vehicle: Any
    # 获取是否按释放时间排序标识
    is_odtime_order: Any
    # 获取时间窗未排lpn数阈值
    tw_unfinished_limit: Any
    # 出货口分配信息
    port_assignment_map: Any
    # 楼层对应速度
    floor_speed_map = {}
    # 楼层出货口数量
    floor_port_num_map = {}
    # 楼层对应同时交付工厂数
    floor_delivery_num_map = {}

    def _pre_process(self):
        self.context.app.logger.info("[TW] 查询数据库配置")
        # 获取所有配置信息
        config_data = TaskDataService().get_config_data()
        # 转换为字典
        config_data_map = {item['code']: item['value'] for item in config_data}
        self.context.app.logger.info("[TW] 获取到配置信息为：%s", config_data_map)
        # 获取出货口配置信息
        self.port_config_list = TaskDataService().get_port_config_data()
        # 获取打折系数
        self.dis_value = config_data_map.get("redfactor", None)
        # 获取打折系数
        self.box_flow_value = float(config_data_map.get("box_flow")) / 3600
        # 获取计算时间
        self.execution_time = float(config_data_map.get("time_window_execution_time"))
        # 获取是否按释放时间排序标识
        self.is_odtime_order = config_data_map.get("is_odtime_order")
        # 获取时间窗未排lpn数阈值
        self.tw_unfinished_limit = config_data_map.get("tw_unfinished_limit")
        self.context.app.logger.info("[TW] 获取到配置计算时间为：%s", self.execution_time)
        # 获取是否分车标识
        self.is_split_vehicle = float(config_data_map.get("is_split_vehicle"))
        # 获取出货口对应件箱总数
        self.port_lpn_num = TaskDataService().get_port_lpn_num()
        self.port_assignment_map = defaultdict(list)
        for item in TaskDataService().get_port_assignment_data():
            key = item['code'].split('-')[0]
            value = [int(item['code'].split('-')[1]), int(item['value'])]
            self.port_assignment_map[key].append(value)
        self.port_assignment_map = dict(self.port_assignment_map)
        self.context.app.logger.info('[TW] 获取出货口分配信息为 %s', self.port_assignment_map)

        # 分配楼层对应出货口信息
        for port_config in self.port_config_list:
            speed = port_config['flow'] / 3600
            num = port_config['total_port_number']
            deliver_count = int(port_config['delivery_factory_num'])
            delivery_target_type = port_config['delivery_target_type']
            self.floor_speed_map[delivery_target_type] = speed
            self.floor_port_num_map[delivery_target_type] = num
            self.floor_delivery_num_map[delivery_target_type] = deliver_count

        self.context.app.logger.info('[TW] 获取楼层对应速度为 %s', self.floor_speed_map)
        self.context.app.logger.info('[TW] 获取楼层出货口数量为 %s', self.floor_port_num_map)
        self.context.app.logger.info('[TW] 获取楼层对应同时交付工厂数为 %s', self.floor_delivery_num_map)

        # 获取全局时间
        self.global_time = DataProcessor.to_arr_global_time(TaskDataService().get_global_time())
        self.context.app.logger.info("[TW] 查询数据库配置完成")
        # 检查数据问题
        DataChecker(self.context).in_data_check()
        DataChecker(self.context).config_data_check(self.dis_value, self.port_config_list, self.port_lpn_num)

    def _process(self):
        # 入库对象列表
        vehicle_task_list = []
        vehicle_order_detail_list = []
        wave_order_sku_list = []
        merge_wave_order_sku_list = []

        if self.context.response_message is not None:
            return

        data = self.context.in_data
        task_service = TaskDataService()
        # ems转化系数
        pallet_to_case_list = []
        # ems浮动系数
        cl_pallet_list = []
        # ems车容量
        vehicle_pallet_list = []
        # ems对应出货口速度
        v_j = [0, 0, 0]
        ems_goods_num = []
        # ems货物数量
        ems_pcs_num = []
        # ems出货口
        ems_port_num = []
        # ems楼层信息
        ems_floor = []
        # ems开始时间
        ems_begin_time = []
        # ems截止时间
        ems_end_time = []
        # ems订单详情ID
        ems_sub_task_list = []
        # ems订单详情添加时间
        ems_detail_add_date = []
        # ems交付工厂
        ems_deliver_list = []
        # ems时间间隔
        ems_deliver_interval_list = []
        # ems货物类型
        ems_job_type = []
        # ems优先级
        ems_priority_list = []

        # 自制任务
        zz_pallet_to_case_list = []
        zz_vehicle_pallet_list = []
        zz_cl_pallet_list = []
        zz_goods_num = []
        zz_pcs_num = []
        zz_port_num = []
        # ems楼层信息
        zz_floor = []
        zz_begin_time = []
        zz_end_time = []
        zz_car_list = []
        zz_sub_task_list = []
        # 自制订单详情添加时间
        zz_detail_add_date = []
        zz_deliver_list = []
        zz_deliver_interval_list = []
        zz_job_type = []
        zz_priority_list = []
        # 出货口数量
        port_num_list = [0, 0, 0]
        # 出货口情况
        deliver_port = {}
        # 未排车订单信息
        unload_detail_list = []

        # 分配算法需要速度数组
        for port_config in self.port_config_list:
            num = port_config['total_port_number']
            deliver_count = int(port_config['delivery_factory_num'])
            delivery_pack_type = port_config['delivery_pack_type']
            speed = port_config['flow'] / 3600

            if delivery_pack_type == "3":
                v_j[2] = float(speed)
                port_num_list[2] = num
                self.zz_delivery_count = deliver_count
            if delivery_pack_type == "2":
                v_j[1] = float(speed)
                port_num_list[1] = num
                self.ems_delivery_count = deliver_count
            if delivery_pack_type == "1":
                v_j[0] = float(speed)
                port_num_list[0] = num

        v_se_j = [v_j[0], v_j[2], v_j[1]]  # TODO 需要确认第二个自制口的速度

        # 获取时间窗配置信息
        windows_config_map, deliver_factory_map = (
            DataProcessor.get_windows_config_data(data.get('timeWindowConfigList')))

        # 获取自制装车信息
        vehicle_plan_begin_time_map, vehicle_plan_end_time_map, vehicle_plan_car_num_map = (
            DataProcessor.get_vehicle_plan_data(data.get('wopsSelfProductVehiclePlanList')))

        # 获取交付对象列表以及去往楼层
        plan_floor_map, zz_factory_code_list = DataProcessor.get_zz_and_floor_data(data.get('storerList'))

        # 获取时间窗数据 转化为对应分钟数
        time_window_list = data.get('timeWindowList')
        sorted_time_window_list = sorted(time_window_list,
                                         key=lambda x: datetime.datetime.strptime(x['planBegin'].replace("T", " "),
                                                                                  "%Y-%m-%d %H:%M:%S"))
        time_data_list = DataProcessor.get_time_data(sorted_time_window_list)

        # 获取lpn列表、订单详情相关数据
        lpn_map, storer_map, detail_map, sku_map, detail_factory_code_map, is_continue, response_message = (
            DataProcessor.get_detail_and_lpn_data(data.get('lpnListByOrder'),
                                                  deliver_factory_map, zz_factory_code_list))
        if not is_continue:
            self.context.response_message = response_message
            self.context.app.logger.error(response_message)
            return

        self.context.app.logger.info("[TW] 开始处理算法入参数据")
        # 分配ems出货口
        ems_deliver_factory_goods_port = []
        good_port = []
        port_arr = []
        for port in range(port_num_list[1]):
            port_arr.append(1)
        good_port.append(port_arr)
        plt_port_arr = []
        for port in range(port_num_list[0]):
            plt_port_arr.append(1)
        good_port.append(plt_port_arr)
        ems_deliver_factory_goods_port.append(good_port)
        ems_port_num.append(ems_deliver_factory_goods_port)

        # 开始处理算法入参数据
        for storer_key, items in lpn_map.items():
            storer_consigneekey = storer_key
            storer_key = storer_map.get(storer_key)
            # 判断交付对象楼层信息
            plan_floor = plan_floor_map.get(storer_key)
            if plan_floor is None:
                self.context.app.logger.warning("[TW] 交付对象未匹配到楼层信息: %s", storer_key)
                unload_detail_list.append({'未获取到该交付对象楼层信息': storer_key})
                continue
            # 判断交付对象配置信息
            if windows_config_map.get(storer_key) is None:
                unload_detail_list.append({'未获取到该交付对象配置信息': storer_key})
                continue
            windows_config = windows_config_map.get(storer_key)[0]
            if windows_config is None:
                unload_detail_list.append({'未获取到该交付对象配置信息': storer_key})
                continue
            # 将字符串解析为日期时间对象
            end_time = windows_config.get('deliverConfigEndTime')
            if end_time is None:
                dt_end_obj = None
            else:
                dt_end_obj = datetime.datetime.combine(datetime.datetime.now().date(),
                                                       datetime.datetime.
                                                       strptime(windows_config.get('deliverConfigEndTime'),
                                                                "%H:%M:%S").time())
            min_plan_begin = None
            for time_windows in data["timeWindowList"]:
                plan_begin = datetime.datetime.strptime(time_windows['planBegin'].replace("T", " "),
                                                        "%Y-%m-%d %H:%M:%S")
                if min_plan_begin is None or plan_begin < min_plan_begin:
                    min_plan_begin = plan_begin

            if min_plan_begin is None:
                self.context.response_message = f"{storer_key} 未匹配到时间窗信息"
                return

            dt_begin_obj = datetime.datetime.strftime(min_plan_begin, "%Y-%m-%d %H:%M:%S")
            dt_begin_obj = datetime.datetime.strptime(dt_begin_obj, "%Y-%m-%d %H:%M:%S")
            # 计算从当天零点到该时间的分钟数（截止时间）
            end_minutes = parse_second(dt_end_obj)
            # 计算从当天零点到该时间的分钟数（开始时间）
            begin_minutes = parse_second(dt_begin_obj)

            deliver_factory_good_list = []
            deliver_factory_goods_type = []
            deliver_factory_goods_port = []
            deliver_factory_pcs_list = []
            deliver_factory_detail_list = []

            deliver_factory_map = []

            zz_plan_begin_time_list = []
            zz_plan_end_time_list = []
            zz_plan_car_num_list = []
            order_good_list = []
            order_goods_type = []
            order_pcs_list = []
            detail_list_order = []
            detail_add_date_list = []
            detail_add_date = []
            good_port = []
            port_arr = []
            box_port_num = 0
            if storer_key not in zz_factory_code_list:
                for port in range(port_num_list[1]):
                    port_arr.append(1)
                box_port_num = port_num_list[1]
            else:
                if plan_floor_map.get(storer_key) != '01':
                    port_arr.append(0)
                    port_arr.append(1)
                    box_port_num = port_num_list[1]
                else:
                    for port in range(port_num_list[2]):
                        port_arr.append(1)
                        port_arr.append(0)
                        box_port_num = port_num_list[2]

            good_port.append(port_arr)
            # deliver_port[storer_key] = box_port_num
            deliver_port[storer_key] = self.floor_port_num_map.get(plan_floor_map.get(storer_key))
            plt_port_arr = []
            for port in range(port_num_list[0]):
                plt_port_arr.append(1)
            good_port.append(plt_port_arr)
            for order_detail in items:
                if detail_map.get(order_detail) is None:
                    self.context.response_message = f"[TW] details为空 {order_detail}!"
                    self.context.app.logger.error(f"[TW] details为空 {order_detail}!")
                data_order = detail_map.get(order_detail)[0]
                if data_order is None:
                    self.context.response_message = f"[TW] details为空 {order_detail}!"
                    self.context.app.logger.error(f"[TW] details为空 {order_detail}!")
                plt_list = data_order['pltIdResultDTOS']
                box_list = data_order['boxIdResultDTOS']
                pcs_list = []
                good_list = []
                good_type = []
                if len(plt_list) == 0 and len(box_list) == 0:
                    self.context.app.logger.warning("[TW] details为空 detailId: %s", data_order['orderDetailId'])
                    continue
                if len(plt_list) > 0:
                    for plt in plt_list:
                        pcs_list.append(plt['qty'])
                    good_list.append(len(plt_list))
                    good_type.append(0)
                if len(box_list) > 0:
                    for box in box_list:
                        pcs_list.append(box['qty'])
                    good_list.append(len(box_list))
                    good_type.append(1)
                order_pcs_list.append(pcs_list)
                order_good_list.append(good_list)
                order_goods_type.append(good_type)
                detail_list_order.append(data_order['orderDetailId'])
                detail_add_date.append(
                    parse_second(datetime.datetime.strptime(data_order['orderDetailAddDate'].replace("T", " "),
                                                            "%Y-%m-%d %H:%M:%S.%f")))
            deliver_factory_map.append(storer_consigneekey)
            deliver_factory_goods_port.append(good_port)
            deliver_factory_detail_list.append(detail_list_order)
            detail_add_date_list.append(detail_add_date)
            deliver_factory_good_list.append(order_good_list)
            deliver_factory_goods_type.append(order_goods_type)
            deliver_factory_pcs_list.append(order_pcs_list)
            deliver_interval = windows_config['deliverInterval'] * 60
            if len(order_good_list) == 0:
                self.context.app.logger.warning("[TW] 交付对象pcs数为空 %s", storer_key)
                continue
            if storer_key not in zz_factory_code_list:
                # 添加浮动系数
                cl_pallet_list.append(windows_config['uclPallet'] / 100)
                # 添加装车模板信息
                vehicle_pallet_list.append(windows_config['vehicleLoadPallet'] * windows_config['palletToCase'])
                # 转换系数
                pallet_to_case_list.append(windows_config['palletToCase'])
                ems_priority_list.append(windows_config['factoryPriority'])
                ems_goods_num.append(deliver_factory_good_list)
                ems_pcs_num.append(deliver_factory_pcs_list)
                ems_port_num.append(deliver_factory_goods_port)
                ems_floor.append([plan_floor_map.get(storer_key)])
                ems_job_type.append(deliver_factory_goods_type)
                ems_sub_task_list.append(deliver_factory_detail_list)
                ems_detail_add_date.append(detail_add_date_list)
                ems_begin_time.append(math.ceil(begin_minutes))
                ems_end_time.append(end_minutes)
                ems_deliver_interval_list.append(deliver_interval)
                ems_deliver_list.append(deliver_factory_map)
            else:
                #  如果自制发车
                if not vehicle_plan_begin_time_map.get(storer_key):
                    if self.is_split_vehicle == 1:
                        self.context.app.logger.warning("[TW] 交付对象未找到对应发车列表: %s", storer_key)
                        unload_detail_list.append({'自制缺车未排交付对象': storer_key})
                        continue
                if vehicle_plan_begin_time_map.get(storer_key):
                    for e in vehicle_plan_begin_time_map.get(storer_key):
                        dt_begin_obj = datetime.datetime.strptime(e.replace("T", " "), "%Y-%m-%d %H:%M:%S")
                        begin_minutes = parse_second(dt_begin_obj)
                        zz_plan_begin_time_list.append(begin_minutes)
                    for e in vehicle_plan_end_time_map.get(storer_key):
                        # 计算从当天零点到该时间的分钟数（截止时间）
                        dt_end_obj = datetime.datetime.strptime(e.replace("T", " "), "%Y-%m-%d %H:%M:%S")
                        end_minutes = parse_second(dt_end_obj)
                        zz_plan_end_time_list.append(end_minutes)
                    for e in vehicle_plan_car_num_map.get(storer_key):
                        # 添加每一个时间段 交付对象对应的车数
                        zz_plan_car_num_list.append(e)
                    zz_begin_time.append(zz_plan_begin_time_list)
                    zz_end_time.append(zz_plan_end_time_list)
                    zz_car_list.append(zz_plan_car_num_list)
                else:
                    zz_begin_time.append(math.ceil(begin_minutes))
                    zz_end_time.append(end_minutes)
                # 添加浮动系数
                zz_cl_pallet_list.append(windows_config['uclPallet'] / 100)
                # 添加装车模板信息
                zz_vehicle_pallet_list.append(windows_config['vehicleLoadPallet'] * windows_config['palletToCase'])
                # 转换系数
                zz_pallet_to_case_list.append(windows_config['palletToCase'])
                zz_priority_list.append(windows_config['factoryPriority'])
                zz_goods_num.append(deliver_factory_good_list)
                zz_pcs_num.append(deliver_factory_pcs_list)
                zz_port_num.append(deliver_factory_goods_port)
                zz_floor.append([plan_floor_map.get(storer_key)])
                zz_job_type.append(deliver_factory_goods_type)
                zz_sub_task_list.append(deliver_factory_detail_list)
                zz_detail_add_date.append(detail_add_date_list)
                zz_deliver_interval_list.append(deliver_interval)
                zz_deliver_list.append(deliver_factory_map)

        total_sub_data = ems_sub_task_list + zz_sub_task_list
        ems_detail_index = DataProcessor.generate_element_to_indices_dict(ems_deliver_list)
        zz_detail_index = DataProcessor.generate_element_to_indices_dict(zz_deliver_list)

        self.context.app.logger.info("[TW] 查询已完成跟正在进行的所有装车任务")

        (deliver_plan_time, detail_port_num, detail_id_arr, vehicle_taskid_arr, insert_time, wavelet_order_id, state) \
            = DataProcessor.get_completed_car(task_service, ems_detail_index, zz_detail_index)
        self.context.app.logger.info(f"[TW] 当前小波次最大序列ID:{wavelet_order_id} , state:{state}")
        self.context.app.logger.info("[TW] 处理算法入参数据完成")

        self.context.app.logger.info("[TW] 保存算法入参文件")
        log_contents = {
            "ems_goods_num": ems_goods_num,
            "zz_goods_num": zz_goods_num,
            "ems_job_type": ems_job_type,
            "zz_job_type": zz_job_type,
            "cl_pallet_list": cl_pallet_list,
            "vehicle_pallet_list": vehicle_pallet_list,
            "pallet_to_case_list": pallet_to_case_list,
            "zz_cl_pallet_list": zz_cl_pallet_list,
            "zz_vehicle_pallet_list": zz_vehicle_pallet_list,
            "zz_pallet_to_case_list": zz_pallet_to_case_list,
            "ems_pcs_num": ems_pcs_num,
            "ems_begin_time": ems_begin_time,
            "ems_end_time": ems_end_time,
            "ems_port_num": ems_port_num,
            "v_j": v_j,
            "zz_begin_time": zz_begin_time,
            "zz_end_time": zz_end_time,
            "zz_pcs_num": zz_pcs_num,
            "zz_port_num": zz_port_num,
            "v_se_j": v_se_j,
            "a_c": port_num_list[0],
            "p_num": port_num_list[1],
            "time_windows": time_data_list,
            "dis": self.dis_value,
            "zz_car_list": zz_car_list,
            "zz_deliver_interval_list": zz_deliver_interval_list,
            "ems_deliver_interval_list": ems_deliver_interval_list,
            "zz_priority_list": zz_priority_list,
            "ems_priority_list": ems_priority_list,
            "detail_port_num": detail_port_num,
            "deliver_plan_time": deliver_plan_time,
            "detail_id_arr": detail_id_arr,
            "insert_time": parse_second(insert_time),
            "total_sub_data": total_sub_data,
            "global_time": self.global_time,
            "box_flow_value": self.box_flow_value,
            "ems_delivery_count": self.ems_delivery_count,
            "zz_delivery_count": self.zz_delivery_count,
            "port_lpn_num": self.port_lpn_num,
            "ems_detail_add_date": ems_detail_add_date,
            "zz_detail_add_date": zz_detail_add_date,
            "time_window_execution_time": self.execution_time,
            "is_split_vehicle": self.is_split_vehicle,
            "ems_floor": ems_floor,
            "zz_floor": zz_floor,
            "floor_speed_map": self.floor_speed_map,
            "floor_port_num_map": self.floor_port_num_map,
            "floor_delivery_num_map": self.floor_delivery_num_map,
            "port_assignment_map": self.port_assignment_map
        }
        write_content = ""
        for key, value in log_contents.items():
            write_content += f"{key}: {str(value)}\n"
        # 将算法入参写入环境变量
        try:
            os.environ['twAlgorithmInput'] = write_content
        except Exception as e:
            self.context.app.logger.error("保存算法入参失败: %s", e)

        # 打印日志
        XTWTaskService.info_log_list(self, log_info=log_contents)

        self.context.app.logger.info("[TW] 时间窗算法模块开始")
        # 调用算法计算
        (end_solution_x_total, solution_bool_sub_job, solution_bool_c, end_sxt, sbsj, sbc, car_list, job_re,
         job_total, job_type_total, job_se_total, job_se_type_total, pcs_num,
         total_d_num, total_d_goods, zz_r, no_car_re, no_job_data_re) = (
            main_fun(ems_goods_num, ems_begin_time, ems_end_time, ems_job_type, ems_port_num, v_j,
                     ems_pcs_num,
                     zz_goods_num, zz_begin_time, zz_end_time, zz_job_type, zz_pcs_num, zz_port_num,
                     v_se_j,
                     cl_pallet_list, zz_cl_pallet_list,
                     vehicle_pallet_list,
                     zz_vehicle_pallet_list,
                     pallet_to_case_list,
                     zz_pallet_to_case_list,
                     port_num_list[0], port_num_list[1],
                     time_data_list,
                     float(self.dis_value),
                     zz_car_list,
                     self.execution_time, self.execution_time,
                     ems_deliver_interval_list,
                     zz_deliver_interval_list, ems_priority_list, zz_priority_list,
                     deliver_plan_time, detail_port_num, detail_id_arr,
                     parse_second(insert_time), self.global_time,
                     self.box_flow_value, self.ems_delivery_count, self.zz_delivery_count,
                     int(self.port_lpn_num[0]), int(self.port_lpn_num[1]), int(self.port_lpn_num[2]),
                     ems_detail_add_date, zz_detail_add_date, self.is_split_vehicle,
                     ems_floor, zz_floor, self.floor_speed_map, self.floor_port_num_map,
                     self.floor_delivery_num_map,self.port_assignment_map,
                     logger=self.context.app.logger))

        self.context.app.logger.info("[TW] 时间窗算法模块结束")

        # ems以及自制任务 开始跟结束时间
        solution_x_ems_total = end_solution_x_total
        solution_x_se_total = end_sxt
        # ems以及自制任务 发车列表
        zz_car_list = car_list[len(ems_goods_num):]
        ems_car_list = car_list[:len(ems_goods_num)]
        # ems以及自制任务 货物形态
        zz_job_list = job_re[len(ems_goods_num):]
        ems_job_list = job_re[:len(ems_goods_num)]
        # ems以及自制任务 所有货物数量
        zz_d_num = total_d_num[len(ems_goods_num):]
        ems_d_num = total_d_num[:len(ems_goods_num)]
        # ems以及自制任务 所有pcs
        zz_d_goods = total_d_goods[len(ems_goods_num):]
        ems_d_goods = total_d_goods[:len(ems_goods_num)]

        # 打印日志
        log_info = {
            "solution_x_se_total": solution_x_se_total,
            "solution_x_ems_total": solution_x_ems_total,
            "zz_car_list": zz_car_list,
            "ems_car_list": ems_car_list,
            "zz_job_re": zz_job_list,
            "ems_job_re": ems_job_list,
            "ems_bool_sub_job": solution_bool_sub_job,
            "sbsj": sbsj,
            "solution_bool_c": solution_bool_c,
            "sbc": sbc,
            "job_type_total": job_type_total,
            "job_se_type_total": job_se_type_total,
            "total_d_num": total_d_num,
            "total_d_goods": total_d_goods,
            "zz_data_list": zz_d_num,
            "ems_data_list": ems_d_goods,
            "zz_r": zz_r,
            "no_car_re": no_car_re,
            "no_job_data_re": no_job_data_re
        }
        XTWTaskService.info_log_list(self, log_info)

        self.context.app.logger.info("[TW] 开始处理数据并入库")
        # 自制未排车订单
        DataProcessor.get_unload_car_detail(zz_car_list, sbsj, zz_job_list,
                                            total_sub_data, zz_d_num, no_car_re, unload_detail_list, no_job_data_re)
        # 循环填充自制任务数据
        DataProcessor.parse_task_data(zz_car_list, detail_factory_code_map, job_se_type_total, zz_job_list,
                                      total_sub_data,
                                      zz_d_num, zz_d_goods, sbsj, sbc, solution_x_se_total, time_data_list, sku_map,
                                      sorted_time_window_list, zz_r, deliver_port, vehicle_task_list,
                                      vehicle_order_detail_list,
                                      wave_order_sku_list)
        # ems未排车订单
        DataProcessor.get_unload_car_detail(ems_car_list, solution_bool_sub_job, ems_job_list,
                                            total_sub_data, ems_d_num, no_car_re, unload_detail_list, no_job_data_re)
        # 填充ems任务数据
        DataProcessor.parse_task_data(ems_car_list, detail_factory_code_map, job_type_total, ems_job_list,
                                      total_sub_data,
                                      ems_d_num, ems_d_goods, solution_bool_sub_job, solution_bool_c,
                                      solution_x_ems_total,
                                      time_data_list, sku_map, sorted_time_window_list, None, deliver_port,
                                      vehicle_task_list,
                                      vehicle_order_detail_list, wave_order_sku_list)

        # 创建一个默认字典，用于存储合并后的对象
        merged_dict = defaultdict(lambda: WaveOrderSku(
            is_urgent=0, sku=None, orderdetil=None, num=0,
            deliver_factory=None, deliver_factory_code=None,
            wops_delivery_time_windowid=None, wops_vehicle_taskid=None,
            pallet_num=0, pallet_pcs_num=0, box_num=0, box_pcs_num=0
        ))
        # 遍历对象列表
        for sku in wave_order_sku_list:
            key = (sku.orderdetil, sku.wops_delivery_time_windowid, sku.wops_vehicle_taskid)
            # 如果键已经存在，则更新相应属性
            if key in merged_dict:
                merged_dict[key].pallet_num += sku.pallet_num
                merged_dict[key].pallet_pcs_num += sku.pallet_pcs_num
                merged_dict[key].box_num += sku.box_num
                merged_dict[key].box_pcs_num += sku.box_pcs_num
                merged_dict[key].num += sku.num
            else:
                # 否则，将对象添加到字典中
                merged_dict[key] = sku
        # 将字典中的值转换回 WaveOrderSku 对象列表
        merge_wave_order_sku_list.extend(list(merged_dict.values()))

        # 开始入库
        VehicleOrderService.save_task_order(vehicle_order_detail_list, vehicle_taskid_arr)
        VehicleOrderService.save_task(vehicle_task_list)
        VehicleOrderService.save_wave_order(merge_wave_order_sku_list)

        self.context.app.logger.info("[TW] 入库完成, wave_order_sku num: %s, vehicle_order_detail num: %s,"
                                     " vehicle_task num: %s",
                                     len(merge_wave_order_sku_list), len(merge_wave_order_sku_list),
                                     len(vehicle_task_list))
        self.context.app.logger.info("unload_detail_list: %s", unload_detail_list)
        # 初始化一个空字典来存储合并后的详情
        merged_unload_details = {}
        # 遍历jobs列表生成未排订单的详情
        for detail in unload_detail_list:
            if detail.get('自制缺车未排订单ID') is not None:
                detail_id = detail.get('自制缺车未排订单ID')
                box_num, pallet_num = (detail.get('未排件箱数'), detail.get('未排栈板数'))
                # 如果detail_id已经在字典中，则累加件箱数和栈板数
                if detail_id in merged_unload_details:
                    if merged_unload_details[detail_id].get('未排件箱数') is None:
                        continue
                    merged_unload_details[detail_id]['未排件箱数'] += box_num
                    merged_unload_details[detail_id]['未排栈板数'] += pallet_num
                    # 如果detail_id不在字典中，则创建新的条目
                else:
                    merged_unload_details[detail_id] = {'自制缺车未排订单ID': detail_id, '未排件箱数': box_num,
                                                        '未排栈板数': pallet_num}
            elif detail.get('未获取到该交付对象配置信息') is not None:
                storer_key = detail.get('未获取到该交付对象配置信息')
                merged_unload_details[storer_key] = {'未获取到该交付对象配置信息': storer_key}
            elif detail.get('未获取到该交付对象楼层信息') is not None:
                storer_key = detail.get('未获取到该交付对象楼层信息')
                merged_unload_details[storer_key] = {'未获取到该交付对象楼层信息': storer_key}
            elif detail.get('自制缺车未排交付对象') is not None:
                detail_id = detail.get('自制缺车未排交付对象')
                merged_unload_details[detail_id] = {'自制缺车未排交付对象': detail_id}
            else:
                detail_id = detail.get('未排订单ID')
                box_num, pallet_num = (detail.get('未排件箱数'), detail.get('未排栈板数'))
                # 如果detail_id已经在字典中，则累加件箱数和栈板数
                if detail_id in merged_unload_details:
                    if merged_unload_details[detail_id].get('未排件箱数') is None:
                        continue
                    merged_unload_details[detail_id]['未排件箱数'] += box_num
                    merged_unload_details[detail_id]['未排栈板数'] += pallet_num
                    # 如果detail_id不在字典中，则创建新的条目
                else:
                    merged_unload_details[detail_id] = {'未排订单ID': detail_id, '未排件箱数': box_num,
                                                        '未排栈板数': pallet_num}

                # 将合并后的详情字典转换为列表
        details = list(merged_unload_details.values())
        self.context.app.logger.warning("未排订单列表: %s", details)
        self.context.result = details

    def info_log_list(self, log_info):
        for key, value in log_info.items():
            self.context.app.logger.info("[TW] %s: %s", key, value)

    def info_log(self, key, value):
        self.context.app.logger.info("[TW] %s: %s", key, value)
